from typing import Dict, List, Any, Optional
from repositories.share_189_repository import Share189Repository
from utils.share_utils import get_tianyi_share_data
from datetime import datetime
import json

class Share189Service:
    """189分享码业务逻辑层"""
    
    def __init__(self):
        self.repository = Share189Repository()
    
    def add_share_codes(self, share_items: List[Dict[str, Any]]) -> Dict[str, Any]:
        """批量添加分享码"""
        try:
            # 验证输入数据
            for item in share_items:
                if not item.get('shareCode'):
                    raise ValueError("分享码不能为空")
                if len(item['shareCode']) > 50:
                    raise ValueError("分享码长度不能超过50个字符")
                if item.get('accessCode') and len(item['accessCode']) > 20:
                    raise ValueError("访问码长度不能超过20个字符")
                if item.get('description') and len(item['description']) > 500:
                    raise ValueError("描述信息长度不能超过500个字符")
            
            # 批量创建
            result = self.repository.batch_create(share_items)
            return result
            
        except Exception as e:
            raise e
        finally:
            self.repository.close_session()
    
    def preview_share_code(self, share_code: str, access_code: str = "", depth: int = 3) -> Dict[str, Any]:
        """预览分享码（不存储到数据库）"""
        try:
            # 直接调用解析工具获取分享码数据
            parse_result = get_tianyi_share_data(
                share_code=share_code,
                access_code=access_code,
                depth=depth
            )
            
            if parse_result.get('success'):
                # 提取分享信息和文件树
                share_info = parse_result.get('shareInfo', {})
                file_info = parse_result.get('fileInfo', [])
                statistics = parse_result.get('statistics', {})
                
                return {
                    'success': True,
                    'shareInfo': {
                        'shareId': share_info.get('shareId'),
                        'shareName': share_info.get('shareName'),
                        'shareCode': share_code,
                        'creator': share_info.get('creator', {}),
                        'shareMode': share_info.get('shareMode'),
                        'fileSize': share_info.get('fileSize'),
                        'isFolder': share_info.get('isFolder')
                    },
                    'fileTree': file_info,
                    'statistics': {
                        'totalFiles': statistics.get('totalFiles', 0),
                        'totalFolders': statistics.get('totalFolders', 0),
                        'totalSize': statistics.get('totalSize', 0),
                        'fileTypes': statistics.get('fileTypes', {}),
                        'maxDepthReached': statistics.get('maxDepthReached', 0)
                    }
                }
            else:
                return {
                    'success': False,
                    'message': parse_result.get('message', '解析失败'),
                    'shareCode': share_code
                }
                
        except Exception as e:
            return {
                'success': False,
                'message': str(e),
                'shareCode': share_code
            }
    
    def get_share_list(self, status: Optional[int] = None, keyword: Optional[str] = None,
                      page: int = 1, page_size: int = 20) -> Dict[str, Any]:
        """获取分享码列表"""
        try:
            # 参数验证
            if page < 1:
                page = 1
            if page_size < 1 or page_size > 100:
                page_size = 20
            if status is not None and status not in [0, 1, 2, 3, 4]:
                raise ValueError("无效的状态值")
            
            result = self.repository.get_list(status, keyword, page, page_size)
            return result
            
        except Exception as e:
            raise e
        finally:
            self.repository.close_session()
    
    def get_share_detail(self, share_id: int) -> Dict[str, Any]:
        """获取分享码详情"""
        try:
            share_obj = self.repository.get_by_id(share_id)
            if not share_obj:
                raise ValueError("分享码不存在")
            
            return share_obj.to_dict()
            
        except Exception as e:
            raise e
        finally:
            self.repository.close_session()
    
    def parse_share_code(self, share_id: int, force: bool = False, depth: int = 3) -> Dict[str, Any]:
        """解析分享码"""
        try:
            # 获取分享码记录
            share_obj = self.repository.get_by_id(share_id)
            if not share_obj:
                raise ValueError("分享码不存在")
            
            # 检查是否需要重新解析
            if not force and share_obj.status == 2:
                # 已解析成功，直接返回结果
                return {
                    'shareId': share_obj.id,
                    'status': share_obj.status,
                    'statusText': share_obj.get_status_text(),
                    'parsedAt': share_obj.parse_end_time.isoformat() if share_obj.parse_end_time else None,
                    'fileTreeJson': share_obj.get_file_tree_json()
                }
            
            # 更新状态为解析中
            self.repository.update_status(share_id, 1)  # 解析中
            
            # 调用解析工具
            parse_result = get_tianyi_share_data(
                share_code=share_obj.share_code,
                access_code=share_obj.access_code or "",
                depth=depth
            )
            
            # 更新解析结果
            self.repository.update_parse_result(share_id, parse_result)
            
            # 重新获取更新后的记录
            updated_share = self.repository.get_by_id(share_id)
            
            if parse_result.get('success'):
                return {
                    'shareId': updated_share.id,
                    'status': updated_share.status,
                    'statusText': updated_share.get_status_text(),
                    'parsedAt': updated_share.parse_end_time.isoformat() if updated_share.parse_end_time else None,
                    'fileTreeJson': parse_result
                }
            else:
                return {
                    'shareId': updated_share.id,
                    'status': updated_share.status,
                    'statusText': updated_share.get_status_text(),
                    'errorMessage': parse_result.get('message', '解析失败'),
                    'parsedAt': updated_share.parse_end_time.isoformat() if updated_share.parse_end_time else None
                }
            
        except Exception as e:
            # 更新状态为解析失败
            try:
                self.repository.update_status(share_id, 3, str(e))
            except:
                pass
            raise e
        finally:
            self.repository.close_session()
    
    def import_files(self, share_id: int, target_folder_id: int, 
                    conflict_strategy: str = 'rename', 
                    preserve_structure: bool = True) -> Dict[str, Any]:
        """导入文件到网盘"""
        try:
            # 获取分享码记录
            share_obj = self.repository.get_by_id(share_id)
            if not share_obj:
                raise ValueError("分享码不存在")
            
            # 检查是否已解析
            if share_obj.status != 2:
                raise ValueError("分享码未解析或解析失败")
            
            # 验证冲突处理策略
            if conflict_strategy not in ['rename', 'skip', 'overwrite']:
                raise ValueError("无效的冲突处理策略")
            
            # 更新导入状态为导入中
            self.repository.update_import_status(share_id, 1)  # 导入中
            
            # TODO: 这里需要实现实际的文件导入逻辑
            # 目前先模拟导入过程
            import time
            time.sleep(1)  # 模拟导入耗时
            
            # 模拟导入成功
            imported_files = share_obj.total_files or 0
            imported_size = share_obj.total_size or 0
            
            # 更新导入状态为成功
            self.repository.update_import_status(
                share_id, 2, imported_files, imported_size
            )
            
            return {
                'shareId': share_id,
                'taskId': share_id,  # 简化处理，使用share_id作为task_id
                'targetFolderId': target_folder_id,
                'status': 2,
                'statusText': '导入成功',
                'totalFiles': imported_files,
                'importedFiles': imported_files,
                'importedSize': imported_size,
                'startedAt': datetime.utcnow().isoformat()
            }
            
        except Exception as e:
            # 更新导入状态为失败
            try:
                self.repository.update_import_status(share_id, 3, error_message=str(e))
            except:
                pass
            raise e
        finally:
            self.repository.close_session()
    
    def delete_share_code(self, share_id: int) -> Dict[str, Any]:
        """删除分享码"""
        try:
            # 检查分享码是否存在
            share_obj = self.repository.get_by_id(share_id)
            if not share_obj:
                raise ValueError("分享码不存在")
            
            # 删除记录
            success = self.repository.delete(share_id)
            
            if success:
                return {
                    'shareId': share_id,
                    'deleted': True,
                    'deletedAt': datetime.utcnow().isoformat()
                }
            else:
                raise Exception("删除失败")
            
        except Exception as e:
            raise e
        finally:
            self.repository.close_session()
    
    def get_statistics(self) -> Dict[str, Any]:
        """获取统计信息"""
        try:
            return self.repository.get_statistics()
        except Exception as e:
            raise e
        finally:
            self.repository.close_session()
    
    def validate_share_code_format(self, share_code: str) -> bool:
        """验证分享码格式"""
        if not share_code:
            return False
        
        # 基本长度检查
        if len(share_code) < 8 or len(share_code) > 50:
            return False
        
        # 字符检查（只允许字母和数字）
        if not share_code.replace('_', '').replace('-', '').isalnum():
            return False
        
        return True
    
    def get_file_tree_preview(self, share_id: int, max_items: int = 100) -> Dict[str, Any]:
        """获取文件树预览（限制返回项目数量）"""
        try:
            share_obj = self.repository.get_by_id(share_id)
            if not share_obj:
                raise ValueError("分享码不存在")
            
            if share_obj.status != 2:
                raise ValueError("分享码未解析成功")
            
            file_tree = share_obj.get_file_tree_json()
            if not file_tree:
                return {'items': [], 'total': 0, 'truncated': False}
            
            # 提取文件信息并限制数量
            file_info = file_tree.get('fileInfo', [])
            
            def flatten_files(files, current_count=0):
                """递归展平文件列表"""
                result = []
                for file_item in files:
                    if current_count >= max_items:
                        break
                    
                    result.append({
                        'id': file_item.get('id'),
                        'name': file_item.get('name'),
                        'size': file_item.get('size'),
                        'isFolder': file_item.get('isFolder'),
                        'path': file_item.get('path'),
                        'depth': file_item.get('depth')
                    })
                    current_count += 1
                    
                    # 如果是文件夹且有子项目，递归处理
                    if file_item.get('children') and current_count < max_items:
                        sub_files, current_count = flatten_files(
                            file_item['children'], current_count
                        )
                        result.extend(sub_files)
                
                return result, current_count
            
            flattened_files, total_processed = flatten_files(file_info)
            
            statistics = file_tree.get('statistics', {})
            total_files = statistics.get('totalFiles', 0)
            
            return {
                'items': flattened_files,
                'total': total_files,
                'truncated': total_processed >= max_items,
                'maxItems': max_items
            }
            
        except Exception as e:
            raise e
        finally:
            self.repository.close_session()